﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace Ledict.Utility.Extension
{
    /// <summary>
    /// Table转实体通用方法 为DataTable扩展方法
    /// </summary>
    /// <remarks>
    /// Create Author:Licw
    /// Create Date：2014-03-06
    /// 
    /// Edit Author:Zhangpeng
    /// Edit Date:2014-05-08
    /// Description:加入DataGridView转DataTable
    /// </remarks>
    public static class DataTableExtensions
    {
        #region Datatable相关
        /// <summary>
        /// 根据提供类型，把DataTable类型转换成对应类型列表
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="dt">数据集</param>
        /// <returns></returns>
        public static IList<T> ConvertToList<T>(this DataTable dt) where T : new()
        {
            //定义泛型集合 
            var list = new List<T>();
            //通过反射，获得此模型的类型 
            Type type = typeof(T);

            //遍历DataTable中所有的数据行  
            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                t = dr.ConvertToEntity<T>();
                //对象添加到泛型集合中 
                list.Add(t);
            }
            return list;
        }

        /// <summary>
        /// 根据提供类型，把DataRow类型转换成对应类型
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="dr">数据</param>
        /// <returns></returns>
        public static T ConvertToEntity<T>(this DataRow dr) where T : new()
        {
            T t = new T();
            // 获得此模型的类型 
            var type = typeof(T);
            // 获得此模型的公共属性 
            var propertys = t.GetType().GetProperties();
            //遍历该对象的所有属性 
            int i = 0;
            foreach (PropertyInfo item in propertys)
            {
                /*属性名与列名不同 
                //检查DataTable是否包含此列（列名==对象的属性名）     
                if (dr.Table.Columns.Contains(item.Name))
                {
                    // 判断此属性是否可写
                    if (!item.CanWrite) continue; //该属性不可写，直接跳出   

                    //取值   
                    object value = dr[item.Name];
                    //如果非空，则赋给对象的属性   
                    if (value != DBNull.Value)
                        item.SetValue(t, value, null);
                }*/

                //按照顺序来处理 要求数据库中顺序与Model相同
                // 判断此属性是否可写
                //该属性不可写，直接跳出
                if (i < dr.ItemArray.Count())
                {
                    if (!item.CanWrite) continue;
                    //取值   
                    object value = dr[i++];
                    //如果非空，则赋给对象的属性(Mysql开放Allow Zero Datetime=True属性后，0000-00-00时间类型会报错，或可在此处判断处理)   
                    if (value != DBNull.Value)
                        item.SetValue(t, value, null);
                }
            }
            return t;
        }
        #endregion

        #region DataGridView add by zhangpeng
        /// <summary>
        /// DataGridView转换成对应的DataTable数据集
        /// </summary>
        /// <param name="dvView">DataGridView</param>
        /// <returns>DataTable数据集</returns>
        public static DataTable ToDataTable(this DataGridView dvView)
        {
            //注：行、列分开处理，考虑到只转换成表框架，而没有真实数据的情况

            var dt = new DataTable();
            //列不为空
            if (dvView != null && dvView.ColumnCount > 0)
            {
                DataColumn dc;
                //表标题列
                for (var i = 0; i < dvView.Columns.Count; i++)
                {
                    dc = new DataColumn
                        {
                            ColumnName = dvView.Columns[i].HeaderText,
                            DataType = GetDefaultType(dvView.Columns[i].ValueType)
                        };
                    dt.Columns.Add(dc);
                }
            }

            //行不为空
            if (dvView != null && dvView.RowCount > 0)
            {
                //数据
                for (int j = 0; j < dvView.Rows.Count; j++)
                {
                    var dr = dt.NewRow();
                    for (var x = 0; x < dvView.Columns.Count; x++)
                    {
                        dr[x] = dvView.Rows[j].Cells[x].Value ?? DBNull.Value;
                    }
                    dt.Rows.Add(dr);
                }
            }
            return dt;

        }

        /// <summary>
        /// 清空DataGridView的数据
        /// </summary>
        /// <param name="dvView"></param>
        public static void ToClearAll(this DataGridView dvView)
        {
            dvView.Tag = null;
            dvView.DataSource = null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private static Type GetDefaultType(Type t)
        {
            if (t == typeof(System.Nullable<DateTime>) || t == typeof(DateTime))
            {
                return typeof(DateTime);
            }
            else if (t == typeof(System.Nullable<int>) || t == typeof(int))
            {
                return typeof(int);
            }
            else if (t == typeof(System.Nullable<bool>) || t == typeof(bool))
            {
                return typeof(bool);
            }
            else if (t == typeof(System.Nullable<double>) || t == typeof(double))
            {
                return typeof(double);
            }
            else if (t == null)
            {
                return typeof(string);
            }
            else
            {
                return t;
            }
        }

        #endregion

    }
}
